/*
    封装请求工具--utils--request.js
    1 初始化 axios 实例
    2 请求拦截器 头部 带上 token
    3 响应拦截器 拿出响应数据 拦截失效 token
    4 导出 axios 实例--函数形式--返回 Promise
*/
import axios from 'axios'
import axiosRetry from 'axios-retry'
import store from '@/store'
import router from '@/router'

// 导出 URL  其他不是通过axios 请求的地址 使用这个
// https://apipc-xiaotuxian-front.itheima.net/
// http://pcapi-xiaotuxian-front-devtest.itheima.net/
export const baseURL = 'http://pcapi-xiaotuxian-front-devtest.itheima.net/'

// 1 创建 axios实例
const instance = axios.create({
	baseURL,
	timeout: 5000,
})
// 2 axios   拦截器
// 请求 成功  失败   发请求之前拦截
// use 里面两个   回调函数 config为回调函数参数   成功与失败对应执行
// 拦截后一定要返回出去  config 不然下以后的axios就无法获取config
instance.interceptors.request.use(
	config => {
		// 拦截后做什么  也可create时处理
		// 1 config.headers config.url 等处理config
		// 2 弹框等 延时组件  完事后 响应拦截去掉
		// 3 登录等 要携带信息token  没有可以跳转对应界面

		// 如果本地存在token  就携带token  vuex
		// 1获取用户信息 对象
		const { profile } = store.state.user
		// 2判断是否有token
		if (profile && profile.token) {
			// 3携带token
			config.headers.Authorization = `Bearer ${profile.token}`
		} else {
			// 4没有token 跳转登录
			// router.push('/login')
		}
		// 最后返回出去 处理后的config
		return config
	},
	err => Promise.reject(err)
)
// 3 响应 成功  失败   回调函数  数据返回之前拦截
instance.interceptors.response.use(
	//  最后返回出去 处理后的v  后台数据
	v => v.data,
	e => {
		/*
		    token 验证失败 且是401 携带当前路由进入登录页,登陆成功返回当前页
		    401 进入该函数
         1 清空无效用户信息
         2 跳转到登录页面
         3 跳转到登录页面 应携带当前路由地址 以便跳回  取 route.query.redirectUrl
				 组件中‘/user?a=10&b=1’ $route.path === /user   携带数据丢失
				                   $route.fullPath === /user?a=10
				 router.currentRoute 是 ref响应式 数据  .value
				 ? & 等特殊字符要转码 encodeURIComponent  防止解析地址错误
      */
		if (e.response && e.response.status === 401) {
			store.commit('user/setUser', {})
			const fullPath = encodeURIComponent(router.currentRoute.value.fullPath)
			router.push(`/login?redirectUrl=${fullPath}`)
		}
		return Promise.reject(e)
	}
)
// 配置axios-retry
// 传入axios实例 要放在 request response 后  否则重试但无法触发 then catch
axiosRetry(instance, {
	retries: 2, // 设置自动发送请求次数
	retryDelay: () => 0.5 * 1000, // 重复请求延迟（毫秒）
	shouldResetTimeout: true, //  重置超时时间
	// return true为打开自动发送请求，false为关闭自动发送请求
	retryCondition: error => error.message.includes('timeout'),
})
/*
   4 返回 promise
   请求地址 请求方式 请求数据
   1 get params 来提交 submitData
   2 post data 提交 submitData
   { [ 可写 表达式 ] : value} 动态 key
    get Get  GET   统一转为小写 toLowerCase()
*/
export default (url, submitData, method = 'GET') =>
	// 3 发送网络请求   返回一个 fulfill 状态的axios
	// 即promise  v.data  为服务器返回数据 v包含6个
	instance({
		method,
		url,
		[method.toLowerCase() === 'get' ? 'params' : 'data']: submitData,
	})
